package io.singulart.bottomnavigationbar;

import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.render.Arc;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.render.Path;
import ohos.agp.utils.Color;
import ohos.agp.utils.Rect;
import ohos.agp.utils.RectFloat;
import ohos.app.Context;
import ohos.multimodalinput.event.TouchEvent;

/**
 * CenterNavigationButton
 */
public class CenterNavigationButton extends Component implements Component.DrawTask, Component.TouchEventListener {
    private int mBackgroundColor = Color.WHITE.getValue();

    private int mForegroundColor = Color.WHITE.getValue();
    private int mForegroundColorNormal = Color.WHITE.getValue();

    private Path mBtnPath = new Path();

    private Path mBtnForegroundPath = new Path();

    private Paint mBtnPaint = new Paint();

    private Paint mBtnForegroundPaint = new Paint();

    private Paint mBtnForegroundArcPaint = new Paint();

    private RectFloat mCenterArcRect = new RectFloat();

    private ButtonState mButtonState;

    private BottomNavigationBar mBottomNavigationBar;

    private float tX = -1;
    private float tY = -1;

    public CenterNavigationButton(Context context) {
        this(context, null);
    }

    public CenterNavigationButton(Context context, AttrSet attrs) {
        this(context, attrs, null);
    }

    public CenterNavigationButton(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        initAttr(attrSet);
        init();
    }

    private void initAttr(AttrSet attrSet) {
        if (attrSet == null) {
            return;
        }
        mBackgroundColor = AttrUtils.getAttrSetColor(attrSet, Constants.CEN_BACK_COLOR, Color.WHITE);
        mForegroundColor = AttrUtils.getAttrSetColor(attrSet, Constants.CEN_FORE_COLOR, Color.WHITE);
        mForegroundColorNormal = AttrUtils.getAttrSetColor(attrSet, Constants.CEN_FORE_COLOR_NORMAL, Color.WHITE);
    }

    private void init() {
        setUp();
        addDrawTask(this);
        setTouchEventListener(this);
    }

    /**
     * set BackAndForeColor
     *
     * @param backgroundColor            int
     * @param foregroundColor            int
     * @param foregroundColorNormalColor int
     */
    public void setBackAndForeColor(int backgroundColor, int foregroundColor, int foregroundColorNormalColor) {
        this.mForegroundColorNormal = foregroundColorNormalColor;
        if (mBtnPaint != null) {
            mBtnPaint.setColor(new Color(backgroundColor));
        }
        if (mBtnForegroundPaint != null) {
            mBtnForegroundPaint.setColor(new Color(foregroundColor));
        }
        invalidate();
    }

    /**
     * set BackgroundColor
     *
     * @param backgroundColor int
     */
    public void setBackgroundColor(int backgroundColor) {
        this.mBackgroundColor = backgroundColor;
        mBtnPaint.setColor(new Color(backgroundColor));
        invalidate();
    }

    /**
     * set ForegroundColor
     *
     * @param foregroundColor int
     */
    public void setForegroundColor(int foregroundColor) {
        this.mForegroundColor = foregroundColor;
        mBtnForegroundPaint.setColor(new Color(foregroundColor));
        invalidate();
    }

    /**
     * set ForegroundColorNormal
     *
     * @param foregroundColorNormal int
     */
    public void setForegroundColorNormal(int foregroundColorNormal) {
        this.mForegroundColorNormal = foregroundColorNormal;
        invalidate();
    }

    /**
     * set BottomNavigationBar
     *
     * @param bottomNavigationBar BottomNavigationBar
     */
    public void setBottomNavigationBar(BottomNavigationBar bottomNavigationBar) {
        this.mBottomNavigationBar = bottomNavigationBar;
    }

    /**
     * set Button State
     *
     * @param buttonState ButtonState
     */
    public void setButtonState(ButtonState buttonState) {
        this.mButtonState = buttonState;
        invalidate();
    }

    @Override
    public boolean onTouchEvent(Component component, TouchEvent event) {
        switch (event.getAction()) {
            case TouchEvent.PRIMARY_POINT_DOWN:
                tX = event.getPointerPosition(0).getX();
                tY = event.getPointerPosition(0).getY();
                invalidate();
                return true;
            case TouchEvent.PRIMARY_POINT_UP:
                tX = -1;
                tY = -1;

                Rect view = new Rect(getLeft(), getTop(), getRight(), getBottom());
                if (view.getIntersectRect(
                        new Rect(
                                (int) event.getPointerPosition(0).getX() - Constants.USER_CLICK_OFFSET,
                                (int) event.getPointerPosition(0).getY() - Constants.USER_CLICK_OFFSET,
                                (int) event.getPointerPosition(0).getX() + Constants.USER_CLICK_OFFSET,
                                (int) event.getPointerPosition(0).getY() + Constants.USER_CLICK_OFFSET))) {
                    setButtonState(ButtonState.PRESSED);
                    if (mBottomNavigationBar != null) {
                        mBottomNavigationBar.setLastSelectedItem(2);
                    }
                }
                invalidate();
                return true;
        }
        return false;
    }

    private void setUp() {
        mBtnPaint.setStyle(Paint.Style.FILL_STYLE);
        mBtnPaint.setAntiAlias(true);
        mBtnPaint.setColor(new Color(mBackgroundColor));

        mBtnForegroundPaint.setStyle(Paint.Style.FILL_STYLE);
        mBtnForegroundPaint.setAntiAlias(true);
        mBtnForegroundPaint.setColor(new Color(mForegroundColor));

        mBtnForegroundArcPaint.set(mBtnForegroundPaint);
        mBtnForegroundArcPaint.setStyle(Paint.Style.STROKE_STYLE);
        mBtnForegroundArcPaint.setStrokeWidth(9);
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        mBtnForegroundArcPaint.setColor(
                new Color(mButtonState == ButtonState.PRESSED ? mForegroundColor : mForegroundColorNormal));
        mBtnForegroundPaint.setColor(
                new Color(mButtonState == ButtonState.PRESSED ? mForegroundColor : mForegroundColorNormal));

        float cX = getCenterWidth();
        float cY = getCenterHeight();
        float cbSize = Math.min(cX, cY) - 10;

        mBtnPath.rewind();
        mBtnPath.moveTo(cX, cY);
        mBtnPath.addCircle(cX, cY, cbSize, Path.Direction.CLOCK_WISE);
        mBtnPath.close();

        mBtnForegroundPath.rewind();
        mBtnForegroundPath.moveTo(cX, cY);
        mBtnForegroundPath.addCircle(cX, cY, cbSize * 0.2F, Path.Direction.CLOCK_WISE);

        canvas.drawPath(mBtnPath, mBtnPaint);
        canvas.drawPath(mBtnForegroundPath, mBtnForegroundPaint);

        float offSet = 0.25F;

        mCenterArcRect.modify(
                cX - ((cbSize * offSet) * 2),
                cY - ((cbSize * offSet) * 2),
                cX + ((cbSize * offSet) * 2),
                cY + ((cbSize * offSet) * 2));

        double cXOnCircle = cX + mCenterArcRect.getWidth() / 2 * Math.cos(315D * Math.PI / 180);
        double cYOnCircle = cY + mCenterArcRect.getWidth() / 2 * Math.sin(315D * Math.PI / 180);

        canvas.drawCircle(
                (float) cXOnCircle, (float) cYOnCircle, mBtnForegroundArcPaint.getStrokeWidth(), mBtnForegroundPaint);

        canvas.drawCircle(
                cX, cY - ((cbSize * offSet) * 2), mBtnForegroundArcPaint.getStrokeWidth() / 2, mBtnForegroundPaint);
        canvas.drawCircle(
                cX + ((cbSize * offSet) * 2), cY, mBtnForegroundArcPaint.getStrokeWidth() / 2, mBtnForegroundPaint);

        canvas.drawArc(mCenterArcRect, new Arc(270, -270, false), mBtnForegroundArcPaint);

        mCenterArcRect.modify(10, 10, getWidth() - 10, getHeight() - 10);
        // Calculating on circle position
        double cXOnArc = cX + mCenterArcRect.getWidth() / 2 * Math.cos(45D * Math.PI / 180);
        double cYOnArc = cY + mCenterArcRect.getWidth() / 2 * Math.sin(45D * Math.PI / 180);
        double cXOnArc1 = cX + mCenterArcRect.getWidth() / 2 * Math.cos(134D * Math.PI / 180);
        double cYOnArc1 = cY + mCenterArcRect.getWidth() / 2 * Math.sin(134D * Math.PI / 180);

        canvas.drawCircle(
                (float) cXOnArc, (float) cYOnArc, mBtnForegroundArcPaint.getStrokeWidth() / 2, mBtnForegroundPaint);
        canvas.drawCircle(
                (float) cXOnArc1, (float) cYOnArc1, mBtnForegroundArcPaint.getStrokeWidth() / 2, mBtnForegroundPaint);

        canvas.drawArc(mCenterArcRect, new Arc(45, 90, false), mBtnForegroundArcPaint);
    }

    private float getCenterWidth() {
        return getWidth() / 2F;
    }

    private float getCenterHeight() {
        return getHeight() / 2f;
    }
}
